package com.live.stamp.web.stamp.service.impl;

import com.live.stamp.base.constants.Constants;
import com.live.stamp.base.service.impl.BaseSupportServiceImpl;
import com.live.stamp.base.token.UserModelUtil;
import com.live.stamp.base.utils.BaseUtils;
import com.live.stamp.base.utils.DateUtils;
import com.live.stamp.base.utils.UUIDUtils;
import com.live.stamp.global.commonenum.ListTypeEnum;
import com.live.stamp.global.commonenum.OrderTypeEnum;
import com.live.stamp.web.message.service.MessageService;
import com.live.stamp.web.stamp.baseDataService.StampDataService;
import com.live.stamp.web.stamp.model.TStampComment;
import com.live.stamp.web.stamp.model.TStampInfo;
import com.live.stamp.web.stamp.model.TStampInfoPic;
import com.live.stamp.web.stamp.model.TStampLike;
import com.live.stamp.web.stamp.service.StampService;
import com.live.stamp.web.stamp.vo.TStampInfoVo;
import com.live.stamp.web.user.model.TUser;
import com.live.stamp.web.user.service.UserService;
import com.live.stamp.web.user.vo.TUserVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.boot.container.core.common.BusinessException;
import org.springframework.boot.container.core.common.PageVO;
import org.springframework.boot.container.core.log.ZKLogger;
import org.springframework.boot.container.core.log.ZKLoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.*;

/**
 * 印记service
 * @author cwd E-mail: wendong.cao@jsxfedu.com
 * @version 1
 * @date 2018/4/13 14:37
 */
@Service
public class StampServiceImpl extends BaseSupportServiceImpl implements StampService {
    private static final ZKLogger logger = ZKLoggerFactory.getLogger(StampServiceImpl.class);

    @Resource
    StampDataService stampDataService;
    @Resource
    MessageService messageService;

    @Resource
    UserService userService;

    @Override
    public String sendStamp(TStampInfoVo tStampInfoVo) throws BusinessException {
        logger.info("enter method sendStamp , param tStampInfoVo:{}", tStampInfoVo);

        TUser tUser = UserModelUtil.getUserModel();
        if(tUser == null) {
            throw new BusinessException("发送失败，用户信息为空。");
        }

        TStampInfo tStampInfo = new TStampInfo();
        BaseUtils.copyProperties(tStampInfo, tStampInfoVo);
        tStampInfo.setId(UUIDUtils.getUUID());
        tStampInfo.setCreateTime(new Date());
        tStampInfo.setState("1");
        tStampInfo.setTUserId(tUser.getId());

        stampDataService.addStamp(tStampInfo);          //增加印记

        tStampInfoVo.setId(tStampInfo.getId());
        List<TStampInfoPic> tStampInfoPics = getStampPicsByStampInfo(tStampInfoVo);
        if (tStampInfoPics!=null && tStampInfoPics.size()>0) {          //印记图片
            stampDataService.addStampPic(tStampInfoPics);
        }

        return null;
    }

    @Override
    public String deleteStamp(String id) throws BusinessException {
        logger.info("enter method deleteStamp , param id:{}", id);
        stampDataService.deleteStamp(id);
        return null;
    }

    @Override
    public String likeStamp(TStampInfoVo tStampInfoVo) throws BusinessException {
        logger.info("enter method likeStamp , param tStampInfoVo:{}", tStampInfoVo);

        TUser tUser = UserModelUtil.getUserModel();
        if(tUser == null) {
            throw new BusinessException("点赞失败，用户信息为空。");
        }

        stampDataService.addStampLikeCount(tStampInfoVo.getId());

        TStampLike tStampLike = new TStampLike();
        tStampLike.setCreateTime(new Date());
        tStampLike.setTInjiInfoId(tStampInfoVo.getId());
        tStampLike.setTUserId(tUser.getId());
        tStampLike.setId(UUIDUtils.getUUID());
        stampDataService.addStampLike(tStampLike);

        return null;
    }

    @Override
    public TStampComment commentStamp(TStampInfoVo tStampInfoVo) throws BusinessException {
        logger.info("enter method commentStamp , param tStampInfoVo:{}", tStampInfoVo);
        TUser tUser = UserModelUtil.getUserModel();
        if(tUser == null) {
            throw new BusinessException("评论失败，用户信息为空。");
        }

        stampDataService.addStampCommentCount(tStampInfoVo.getId());

        TStampComment tStampComment = new TStampComment();
        tStampComment.setId(UUIDUtils.getUUID());
        tStampComment.setComment(tStampInfoVo.getComment());
        tStampComment.setTUserId(tUser.getId());
        tStampComment.setCreateTime(new Date());
        tStampComment.setTInjiInfoId(tStampInfoVo.getId());

        stampDataService.addStamppComment(tStampComment);

        messageService.sendCommonStampMessage(tStampComment);            //发送消息

        return tStampComment;
    }

    @Override
    public PageVO<TStampInfoVo> stampList(TStampInfoVo tStampInfoVo, Integer pageNo, Integer pageSize) throws BusinessException {
        logger.info("enter method stampList , param tStampInfoVo:{}", tStampInfoVo);

        TUser tUser = UserModelUtil.getUserModel();
        if(tUser == null) {
            throw new BusinessException("获取好友动态列表失败，用户信息为空。");
        }

        if(pageNo==null || pageNo==0) {           //默认页为第一页
            pageNo = Constants.DEFAULT_PAGE_NO;
        }
        if(pageSize==null || pageSize==0) {         //每页默认10条
            pageSize = Constants.DEFAULT_PAGE_SIZE;
        }
        if(StringUtils.isBlank(tStampInfoVo.getOrderType())) {          //如果排列为空，则默认按时间排序
            tStampInfoVo.setOrderType(OrderTypeEnum.SJ.toString());
        }

        PageVO<TStampInfoVo> tStampInfoVoPageVO = null;

        try {
            if(StringUtils.equals(tStampInfoVo.getOrderType(), OrderTypeEnum.JL.toString())) {      //按距离排序
                tStampInfoVoPageVO = stampListOderByJL(tStampInfoVo, pageNo, pageSize);
            } else {
                tStampInfoVoPageVO = stampListOderByNotJL(tStampInfoVo, pageNo, pageSize);
            }

            addStampsPic(tStampInfoVoPageVO);       //添加图片信息
            ListTypeEnum listTypeEnum = ListTypeEnum.valueOf(tStampInfoVo.getListType());       //列表类型
            switch (listTypeEnum) {             //更新用户查看列表最后时间
                case FRIEND:                //朋友圈
                    userService.updateLookFriendTime(tUser.getId());
                    break;
                case ATTENT:                //关注
                    userService.updateLooAttenTime(tUser.getId());
                    break;
            }

            return tStampInfoVoPageVO;
        }catch (Exception e) {
            logger.error("获取好友印记失败！" + e);
            throw new BusinessException("获取好友印记失败！");
        }
    }

    public void addStampsPic(PageVO<TStampInfoVo> tStampInfoVoPageVO) {
        if(tStampInfoVoPageVO != null) {
            List<TStampInfoVo> tStampInfoVos = tStampInfoVoPageVO.getResult();
            List<TStampInfoPic> tStampInfoPics = null;
            List<TStampInfoVo> _tStampInfoVos = new ArrayList<>();
            for(TStampInfoVo tStampInfoVo : tStampInfoVos) {
                tStampInfoPics = stampDataService.lisStampPicsByStampId(tStampInfoVo.getId());
                if(tStampInfoPics != null) {
                    for(TStampInfoPic tStampInfoPic : tStampInfoPics) {
                        if(StringUtils.isBlank(tStampInfoVo.getPictures())) {
                            tStampInfoVo.setPictures(tStampInfoPic.getPicUrl());
                        } else {
                            tStampInfoVo.setPictures(tStampInfoVo.getPictures() +","+tStampInfoPic.getPicUrl());
                        }
                    }
                }

                _tStampInfoVos.add(tStampInfoVo);
            }

            tStampInfoVoPageVO.setResult(_tStampInfoVos);
        }
    }

    @Override
    public Map<String, Object> stampInfo(TStampInfoVo tStampInfoVo) throws BusinessException {
        logger.info("enter method stampInfo , param tStampInfoVo:{}", tStampInfoVo);

        TUser tUser = UserModelUtil.getUserModel();
        if(tUser == null) {
            throw new BusinessException("操作失败，登录用户为空！");
        }

        Map<String, Object> reslut = new HashMap<>();

        tStampInfoVo = stampDataService.getStampInfo(tStampInfoVo);
        if(tStampInfoVo == null) {
            throw new BusinessException("查看印记失败");
        }

        tStampInfoVo.setIsFriend(userService.isFriend(tUser.getId(), tStampInfoVo.getTUserId())?"1":"0");//是否为好友
        tStampInfoVo.setIsAttent(userService.isAttent(tUser.getId(), tStampInfoVo.getTUserId())?"1":"0");//是否已关注
        tStampInfoVo.setIsLike(isLike(tUser.getId(), tStampInfoVo.getId())?"1":"0");                     //是否已点赞

        List<TStampInfoPic> tStampInfoPics = stampDataService.lisStampPicsByStampId(tStampInfoVo.getId());      //印记图片
        if(tStampInfoPics!=null && tStampInfoPics.size()>0) {
            String pics = "";
            for (TStampInfoPic tsi: tStampInfoPics) {
                if(StringUtils.isNotBlank(tsi.getPicUrl())) {
                    pics += tsi.getPicUrl() + ",";
                }
            }

            if(StringUtils.isNotEmpty(pics)) {
                tStampInfoVo.setPictures(StringUtils.substring(pics, 0, pics.length()-1));
            }
        }

        List<Map> likeList = stampDataService.listLikeByStampId(tStampInfoVo.getId());          //点赞列表
        List<Map> commentList = stampDataService.listCommentByStampId(tStampInfoVo.getId());    //评论列表

        reslut.put("stampInfo", tStampInfoVo);
        reslut.put("likeList", likeList);
        reslut.put("commentList", commentList);

        stampDataService.addStampLookCount(tStampInfoVo.getId());       //查看次数加1

        return reslut;
    }

//    public TStampInfoVo transformDate(TStampInfoVo tStampInfoVo) {
//        if(tStampInfoVo!= null && tStampInfoVo.getCreateTime()!=null) {
//            tStampInfoVo.setCreateTime(DateUtils.showTime(tStampInfoVo.getCreateTime(), "yyyy"));
//        }
//    }

    @Override
    public int stampListCount(TStampInfoVo tStampInfoVo) throws BusinessException {

        logger.info("enter method stampListCount , param tStampInfoVo:{}", tStampInfoVo);
        TUser tUser = UserModelUtil.getUserModel();
        if(tUser == null) {
            throw new BusinessException("获取好友动态数量失败，用户信息为空。");
        }

        TUserVo tUserVo = new TUserVo();
        tUserVo.setId(tUser.getId());
        tUser = userService.getUser(tUserVo);
        if(tUser == null) {
            throw new BusinessException("获取好友动态数量失败，用户信息为空。");
        }

        Map<String, Object> param = new HashMap<>();
        String sql = "select * from t_inji_info where state='1' " ;

        ListTypeEnum listTypeEnum = ListTypeEnum.valueOf(tStampInfoVo.getListType());
        switch (listTypeEnum) {
            case ATTENT:                //关注
                sql += " and tUserId in (select toUserId from t_user_attention where fromUserId=:userId) and createTime>:updateTime";
                param.put("userId", tUser.getId());
                param.put("updateTime", tUser.getLastLookAttenTime());
                break;
            case FRIEND:                //好友
                sql += " and tUserId in (select tUserIdB from t_user_friend where state='1' and tUserIdA=:userId) and createTime>:updateTime";
                param.put("userId", tUser.getId());
                param.put("updateTime", tUser.getLastLookFriendTime());
                break;
        }

        try {
            return this.getDao().count(sql, param);
        } catch (SQLException e) {
            e.printStackTrace();
            logger.error("查询好友动态数量失败" + e);
            throw new BusinessException("查询好友动态数量失败。");
        }
    }

    @Override
    public Map<String, Object> isStampUpdate() throws BusinessException {
        Map<String, Object> data = new HashMap<>();
        TStampInfoVo tStampInfoVo = new TStampInfoVo();
        tStampInfoVo.setListType(ListTypeEnum.FRIEND.toString());
        if(stampListCount(tStampInfoVo) > 0) {
            data.put("friendStamp", "1");
        } else {
            data.put("friendStamp", "0");
        }

        tStampInfoVo.setListType(ListTypeEnum.ATTENT.toString());
        if(stampListCount(tStampInfoVo) > 0) {
            data.put("attenStamp", "1");
        } else {
            data.put("attenStamp", "0");
        }

        return data;
    }

    @Override
    public boolean isLike(String userId, String stampId) throws BusinessException {
        logger.info("enter isLike method,  param userId:{}, stampId:{} ", userId, stampId);

        String sql = "select * from t_inji_like where tInjiInfoId=:stampId and tUserId=:userId";
        Map<String, Object> param = new HashMap<>();
        param.put("stampId", stampId);
        param.put("userId", userId);

        try {
            int count = this.getDao().count(sql, param);
            if(count>=1) {              //如果查询条数大于1说明为好友关系
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
            logger.error("查询是否已点赞失败，" + e.getMessage());
            throw new BusinessException("查询是否已点赞失败，" + e.getMessage());
        }

        return false;
    }

    /**
     * @param tStampInfoVo
     * @return
     */
    private PageVO<TStampInfoVo> stampListOderByJL(TStampInfoVo tStampInfoVo, int pageNo, int pageSize) throws SQLException {

        TUser tUser = UserModelUtil.getUserModel();
        if(tUser == null) {
            throw new BusinessException("获取好友动态列表失败，用户信息为空。");
        }

        Map<String, Object> param = new HashMap<>();
        String sql = "select j.*, u.username, u.photoUrl,j.juli from (select i.*," +
                "ROUND(6378.138*2*ASIN(SQRT(POW(SIN((:latitude*PI()/180-latitude*PI()/180)/2),2)+COS(:latitude*PI()/180)*COS(latitude*PI()/180)*POW(SIN((:longitude*PI()/180-longitude*PI()/180)/2),2)))*1000) AS juli " +
                " from t_inji_info i where i.state='1' ";
        param.put("latitude", tStampInfoVo.getLatitude());
        param.put("longitude", tStampInfoVo.getLongitude());

        if(!StringUtils.equals(tStampInfoVo.getListType(), ListTypeEnum.DISCOVER.toString())) {     //如果不为发现，则添加查询条件
            sql += createSelectSql(tStampInfoVo, param);

            sql += ") j, t_user u where j.tUserId=u.id order by juli asc";
        } else {            //如果为发现，则查询距离所在位置5000米内的印记

            sql += " and i.tUserId not in(select fromUserId from t_user_shield where toUserId=:userId) ";
            param.put("userId", tUser.getId());

            sql += ") j, t_user u where j.tUserId=u.id and juli<=:juli  order by juli asc";
            param.put("juli", Constants.DISCOVER_RANGE);
        }

        return this.getDao().pageQuery(TStampInfoVo.class, sql, param, pageNo, pageSize);
    }

    /**
     * 查看好友动态，非按照距离排列
     * @param tStampInfoVo
     * @return
     */
    private PageVO<TStampInfoVo> stampListOderByNotJL(TStampInfoVo tStampInfoVo, int pageNo, int pageSize) throws SQLException {

        TUser tUser = UserModelUtil.getUserModel();
        if(tUser == null) {
            throw new BusinessException("获取好友动态列表失败，用户信息为空。");
        }
        OrderTypeEnum orderTypeEnum = OrderTypeEnum.valueOf(tStampInfoVo.getOrderType());       //排序类型

        Map<String, Object> param = new HashMap<>();
        String sql = "select i.*,u.username,u.photoUrl from t_inji_info i, t_user u " +
                " where i.tUserId=u.id and i.state='1' ";

        sql += createSelectSql(tStampInfoVo, param);

        switch (orderTypeEnum) {
            case SJ:
                sql += " order by i.createTime desc";
                break;
            case CKS:
                sql += " order by i.lookCount desc";
                break;
            case PLS:
                sql += " order by i.commentCount desc";
                break;
            case DZS:
                sql += " order by i.likeCount desc";
                break;
        }

        return this.getDao().pageQuery(TStampInfoVo.class, sql, param, pageNo, pageSize);
    }

    private String createSelectSql (TStampInfoVo tStampInfoVo, Map<String, Object> paraMap) {
        String sql = "";

        TUser tUser = UserModelUtil.getUserModel();

        if(StringUtils.isNotBlank(tStampInfoVo.getFriendId())) {
            sql += " and i.tUserId=:friendId";
            paraMap.put("friendId", tStampInfoVo.getFriendId());
        } else {

            switch (ListTypeEnum.valueOf(tStampInfoVo.getListType())) {
                case ATTENT:                //关注者
                    sql += " and i.tUserId in (select toUserId from t_user_attention where fromUserId=:userId) ";
                    break;
                case FRIEND:                //好友
                    sql += " and ( i.tUserId in(select tUserIdB from t_user_friend where state='1' and tUserIdA=:userId) ";

//                    if(!StringUtils.equals(tStampInfoVo.getOrderType(), OrderTypeEnum.JL.toString())) {      //非距离排序
                        sql += " or i.tUserId=:userId ";
//                    }

                    sql += " ) ";
                    break;
                case MYSELF:                //我的
                    sql += " and i.tUserId=:userId";
                    break;
            }

            paraMap.put("userId", tUser.getId());
        }

        sql += " and i.tUserId not in(select fromUserId from t_user_shield where toUserId=:userId) ";           //排除屏蔽者的in迹
        paraMap.put("userId", tUser.getId());

        if(StringUtils.isNotBlank(tStampInfoVo.getLabel())) {           //如果label不为空则添加查询条件
            sql += " and i.label=:label";
            paraMap.put("label", tStampInfoVo.getLabel());
        }

        return sql;
    }

    private List<TStampInfoPic> getStampPicsByStampInfo(TStampInfoVo tStampInfoVo) {
        logger.info("enter method getStampPicsByStampInfo , param tStampInfoVo:{}", tStampInfoVo);
        List<TStampInfoPic> reslut = null;

        if(StringUtils.isNotBlank(tStampInfoVo.getPictures())){
            reslut = new ArrayList<>();

            String[] pics = StringUtils.split(tStampInfoVo.getPictures(), ",");
            for (String picUrl: pics) {
                reslut.add(createStampInfoPic(tStampInfoVo, picUrl));
            }
        }

        return reslut;
    }

    private TStampInfoPic createStampInfoPic(TStampInfoVo tStampInfoVo, String picUrl) {
        logger.info("enter method createStampInfoPic , param tStampInfoVo:{}， picUrl:{}", tStampInfoVo, picUrl);
        TStampInfoPic tStampInfoPic = new TStampInfoPic();
        tStampInfoPic.setId(UUIDUtils.getUUID());
        tStampInfoPic.setTInjiInfoId(tStampInfoVo.getId());
        tStampInfoPic.setPicUrl(picUrl);
        tStampInfoPic.setCreateTime(new Date());

        return tStampInfoPic;
    }
}
